package com.zmn.brs.starter.configuration;

import com.zmn.brs.factory.ParseFunctionFactory;
import com.zmn.brs.services.impl.DefaultFunctionServiceImpl;
import com.zmn.brs.services.impl.DefaultParseFunction;
import com.zmn.brs.services.impl.IOperateRecordServiceImpl;
import com.zmn.brs.services.impl.IStaffOperateRecordServiceImpl;
import com.zmn.brs.services.interfaces.IFunctionService;
import com.zmn.brs.services.interfaces.IOperateRecordService;
import com.zmn.brs.services.interfaces.IParseFunction;
import com.zmn.brs.services.interfaces.IStaffOperateRecordService;
import com.zmn.brs.starter.annotation.EnableBusinessRisk;
import com.zmn.brs.starter.support.aop.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import java.util.List;


/**
 * 类描述：操作记录代理自动配置
 *
 * @author xujie
 * @since 2021/03/11 17:25
 * @modifier zhangyao 2021/04/23
 */
@Slf4j
@Configuration
public class OperateRecordProxyAutoConfiguration implements ImportAware {

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public OperateRecordOperationSource operateRecordOperationSource() {

        return new OperateRecordOperationSource();
    }

    @Bean
    @ConditionalOnMissingBean(IFunctionService.class)
    public IFunctionService functionService(ParseFunctionFactory parseFunctionFactory) {

        return new DefaultFunctionServiceImpl(parseFunctionFactory);
    }

    @Bean
    public ParseFunctionFactory parseFunctionFactory(@Autowired List<IParseFunction> parseFunctions) {

        return new ParseFunctionFactory(parseFunctions);
    }

    @Bean
    @ConditionalOnMissingBean(IParseFunction.class)
    public DefaultParseFunction parseFunction() {

        return new DefaultParseFunction();
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public StaffOperateRecordOperationSource staffOperateRecordOperationSource() {

        return new StaffOperateRecordOperationSource();
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryStaffOperateRecordAdvisor staffOperateRecordAdvisor(IFunctionService functionService) {

        BeanFactoryStaffOperateRecordAdvisor advisor = new BeanFactoryStaffOperateRecordAdvisor();
        advisor.setStaffOperateRecordOperationSource(staffOperateRecordOperationSource());
        advisor.setAdvice(staffOperateRecordInterceptor(functionService));
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public StaffOperateRecordInterceptor staffOperateRecordInterceptor(IFunctionService functionService) {

        StaffOperateRecordInterceptor interceptor = new StaffOperateRecordInterceptor();
        interceptor.setStaffOperateRecordOperationSource(staffOperateRecordOperationSource());
        interceptor.setFunctionService(functionService);
        return interceptor;
    }

    @Bean
    @ConditionalOnMissingBean(IStaffOperateRecordService.class)
    @Role(BeanDefinition.ROLE_APPLICATION)
    public IStaffOperateRecordService staffRecordService() {

        return new IStaffOperateRecordServiceImpl();
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryOperateRecordAdvisor operateRecordAdvisor(IFunctionService functionService) {

        BeanFactoryOperateRecordAdvisor advisor = new BeanFactoryOperateRecordAdvisor();
        advisor.setOperateRecordOperationSource(operateRecordOperationSource());
        advisor.setAdvice(operateRecordInterceptor(functionService));
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public OperateRecordInterceptor operateRecordInterceptor(IFunctionService functionService) {

        OperateRecordInterceptor interceptor = new OperateRecordInterceptor();
        interceptor.setOperateRecordOperationSource(operateRecordOperationSource());
        interceptor.setFunctionService(functionService);
        return interceptor;
    }

    @Bean
    @ConditionalOnMissingBean(IOperateRecordService.class)
    @Role(BeanDefinition.ROLE_APPLICATION)
    public IOperateRecordService recordService() {

        return new IOperateRecordServiceImpl();
    }

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {

        AnnotationAttributes enableOperateRecord = AnnotationAttributes.fromMap(
                importMetadata.getAnnotationAttributes(EnableBusinessRisk.class.getName(), false));
        if (enableOperateRecord == null) {
            log.info("@EnableBusinessRisk is not present on importing class");
        }
    }
}
